"""
Looks up reps through seventy.org.  Got some help here from
http://stackoverflow.com/questions/301924/python-urllib-urllib2-httplib-confusion
"""

from BeautifulSoup import BeautifulSoup, SoupStrainer
import re
import urllib
import urllib2

import sys
from os.path import dirname, abspath
sys.path.append(dirname(dirname(abspath(__file__))))
import settings
from django.core.management import setup_environ
setup_environ(settings)

from ourcity.reps import models

class ConnectionError(Exception):
    def __init__(self):
        Exception.__init__(self, 
            'Error connecting to lookup service.  Please try again.')


class NoAddressMatch(Exception):
    def __init__(self):
        Exception.__init__(self, 
            'No match found for that address. Please try another.')


def get_response(address):
    url = 'http://www.phillyvoter.org/locator/ElectedOfficials.aspx'
    first_response = urllib2.urlopen(url)
    session_url = first_response.geturl()
    viewstate_strainer = SoupStrainer('input', attrs={'name': '__VIEWSTATE'})
    viewstate = BeautifulSoup(first_response, parseOnlyThese=viewstate_strainer)
    viewstate_value = viewstate.input['value']
    data = urllib.urlencode({
        '__VIEWSTATE': viewstate_value,
        'txtAddress': address,
    })
    request = urllib2.Request(session_url, data)
    response = urllib2.urlopen(request).read()
    return response

def get_response_dict(address):
    response = get_response(address)
    result_div_strainer = SoupStrainer('div', attrs={'id': 'divResultText'})
    result_div = BeautifulSoup(response, parseOnlyThese=result_div_strainer)
    result_div_texts = result_div.findAll(text=True)
    if result_div_texts[0].startswith(u'Sorry'):
        raise NoAddressMatch
    if result_div_texts[0].strip().startswith(u'No results'):
        raise ConnectionError
    response_dict = {}
    response_dict['reps'] = []
    ward_re = re.compile(r': (\d+)/')
    division_re = re.compile(r'(\d+)$')
    digits_re = re.compile(r'(\d+)')
    for text in result_div_texts:
        if text.startswith('Ward/'):
            response_dict['Ward'] = ward_re.findall(text)[0]
            response_dict['Division'] = division_re.findall(text)[0]
        elif text.startswith('Ci'):
            response_dict['City Council District'] = digits_re.findall(text)[0]
        elif text.startswith('US'):
            response_dict['US Representative District'] = \
                    digits_re.findall(text)[0]
        elif text.startswith('State Senator District'):
            response_dict['State Senate District'] = digits_re.findall(text)[0]
        elif text.startswith('State Representative District'):
            response_dict['State Representative District'] = \
                    digits_re.findall(text)[0]
        else:
            website = text.parent['href'] if text.parent.name == 'a' else ''
            response_dict['reps'].append((unicode(text), website))
    return response_dict

def parse_rep(text, name_re, office):
    name = name_re.findall(text)[0]
    #names = name.strip().split()
    #last_name = names.pop()
    #first_name = ' '.join(names)
    party = PARTY_RE.findall(text)[0]
    website = text.parent['href'] if text.parent.name == 'a' else ''
    phone = PHONE_RE.findall(text)[0].strip()
    return (text, name, office, party, website, phone)

def get_reps(address):
    response_dict = get_response_dict(address)

    one_word_office_name_re = re.compile(r'\w+\s+([^\(]+)')
    two_word_office_name_re = re.compile(r'\w+\s+\w+\s+([^\(]+)')
    party_re = re.compile(r'\((\w)\)')
    phone_re = re.compile(r'\(\w\)(.*)$')

    office_map = {
        'Ward Leader': ('Ward Leader', 'L'),
        'Councilwoman': ('City Councilmember', 'L'),
        'Councilman': ('City Councilmember', 'L'),
        'Representative': ('US Representative', 'F'),
        'State Senator': ('State Senator', 'S'),
        'State Representative': ('State Representative', 'S'),
    }
    district_map = {
        'Ward Leader': 'Ward',
        'City Councilmember': 'City Council District',
        'US Representative': 'US Representative District',
        'State Senator': 'State Senate District',
        'State Representative': 'State Representative District',
    }

    reps = []
    for text, website in response_dict['reps']:
        try:
            rep = models.Representative.objects.get(lookup_string=text)
        except models.Representative.DoesNotExist:
            if text[0] in ('C', 'R'):
                name = one_word_office_name_re.findall(text)[0]
                office_name_level = office_map[text.split()[0]]
            else:
                name = two_word_office_name_re.findall(text)[0]
                office_name_level = office_map[' '.join(text.split()[:2])]
            district_type_name = district_map[office_name_level[0]]
            try:
                district_type = models.DistrictType.objects.get(
                        name=district_type_name)
            except models.DistrictType.DoesNotExist:
                district_type = models.DistrictType(name=district_type_name)
                district_type.save()
            district_name = response_dict[district_type_name]
            try:
                district = models.District.objects.get(
                    type=district_type,
                    name=district_name,
                )
            except models.District.DoesNotExist:
                district = models.District(
                    type=district_type,
                    name=district_name,
                )
                district.save()
            names = name.strip().split()
            last_name = names[-1]
            if last_name in ('Jr.', 'Sr.', 'III'):
                last_name = names[-2]
            try:
                office = models.Office.objects.get(
                    name=office_name_level[0],
                )
            except models.Office.DoesNotExist:
                office = models.Office(
                    name=office_name_level[0],
                )
                office.save()
            party_initial = party_re.findall(text)[0]
            try:
                party = models.Party.objects.get(initial=party_initial)
            except models.Party.DoesNotExist:
                party = models.Party(
                    name='Unknown',
                    initial=party_initial,
                )
                party.save()
            phone = phone_re.findall(text)[0].strip()
            rep = models.Representative(
                    district=district,
                    full_name=' '.join(names),
                    last_name=last_name.strip(', '),
                    level=office_name_level[1],
                    lookup_string=text,
                    office=office,
                    party=party,
                    phone=phone,
                    website=website,
            )
            rep.save()
        reps.append(rep)
        # TODO: add US Senators and Governor
    return reps

if __name__ == '__main__':
    get_reps('abcd')

